#include <common.h>
#include <cvector.h>
#include <filesystem.h>
#include <stdbool.h>
#include <object/building.h>
#include <object/student.h>

#define BUILDINGS_CFG_PATH \
    HOSTEL_MANAGER_HOME_DIR "buildings.cfg"

static cvector(Building) building_list = NULL;

HM_private
void save_buildings(void) {
    FILE *building_cfg = fopen(BUILDINGS_CFG_PATH, "w");

    for (size_t i = 0; i < cvector_size(building_list); ++i) {
        fprintf(
            building_cfg,
            "%zu %zu %zu\n",
            building_list[i].building_id,
            building_list[i].hostel_num,
            (size_t)building_list[i].is_male
        );
    }
    fclose(building_cfg);
}

void register_building(size_t building_id, size_t hostel_num, bool is_male) {
    Building building = {
        .building_id = building_id,
        .hostel_num = hostel_num,
        .is_male = is_male
    };
    cvector_push_back(building_list, building);
    save_buildings();
}

/* return: nums of loaded buildings
 */
HM_private
void load_buildings(void) {
    if (crt_file_if_not_exist(BUILDINGS_CFG_PATH)) {
        HM_throw(InternalError, "please bug report");
    }

    FILE *building_cfg = fopen(BUILDINGS_CFG_PATH, "r");

    char buffer[16] = {0};

    while (read_line(building_cfg, buffer, sizeof(buffer))) {
        size_t building_id, hostels_num, is_male;
        sscanf(buffer, "%zu %zu %zu", &building_id, &hostels_num, &is_male);
        register_building(building_id, hostels_num, is_male);
    }

    fclose(building_cfg);
}

/* @return 0: success, 1: building not found
 */
int unregister_building(size_t building_id) {
    for (size_t i = 0; i < cvector_size(building_list); ++i) {
        if (building_list[i].building_id == building_id) {
            cvector_erase(building_list, i);
            save_buildings();
            return 0;
        }
    }
    return 1;
}

/* @return: 0: success; 1: fail due to building not exists;
 */
int edit_building(size_t building_id, size_t hostel_num, bool is_male) {
    for (size_t i = 0; i < cvector_size(building_list); ++i) {
        if (building_list[i].building_id == building_id) {
            building_list[i].hostel_num = hostel_num;
            building_list[i].is_male = is_male;
            save_buildings();
            return 0;
        }
    }
    return 1;
}

void list_buildings(void) {
    for (size_t i = 0; i < cvector_size(building_list); ++i) {
        printf(
            "building id: %zu, hostel_num: %zu, %s\n",
            building_list[i].building_id,
            building_list[i].hostel_num,
            building_list[i].is_male ? "male" : "female"
        );
    }
}

/* @return NULL if not found
 */
Building* get_building(size_t building_id) {
    for (size_t i = 0; i < cvector_size(building_list); ++i) {
        if (building_list[i].building_id == building_id) {
            return &building_list[i];
        }
    }
    return NULL;
}

void init_building_module(void) {
    crt_file_if_not_exist(BUILDINGS_CFG_PATH);
    load_buildings();
}

void print_vacant_hostels(void) {
    for (size_t i = 0; i < cvector_size(building_list); ++i) {
        size_t count = 0;
        for (size_t hostel_id = 0; hostel_id < building_list[i].hostel_num; ++hostel_id) {
            size_t num = count_students_in_a_hostel(hostel_id);
            if (num == 0) {
                printf("%zu is empty", hostel_id);
                ++count;
            }
        }
        printf(
            "building %zu(%s) has %zu hostels, %zu is vacant hostels\n",
            i,
            building_list[i].is_male ? "male" : "female",
            building_list[i].hostel_num, count
        );
    }
}
